﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using System.Text;
using System.Threading;
using System.Windows.Threading;

namespace JasLib.Threading
{
#if !DOT_NET_4_5_OR_LATER
    /// Having these interfaces declared manually instead of via the future .NET 4.5 framework
    /// at least gets us accustomed to what's coming (they WILL be mandatory for the await keyword).

    /*******************************************************************************************/
    public interface INotifyCompletion
    {
        void OnCompleted(Action continuation);
    }

    /*******************************************************************************************/
    public interface ICriticalNotifyCompletion : INotifyCompletion
    {
        [SecurityCritical]
        void UnsafeOnCompleted(Action continuation);
    }

#endif

    /*******************************************************************************************/
    public abstract class AwaitableBase : INotifyCompletion
    {
        public virtual bool IsCompleted
        {
            get { return true; }
        }

        public virtual void OnCompleted(Action continuation)
        {
            continuation();
            return;
        }
    }

    /*******************************************************************************************/
    public abstract class Awaitable : AwaitableBase
    {
        public Awaitable GetAwaiter()
        {
            return this;
        }

        public virtual void GetResult()
        {
            return;
        }
    }

    /*******************************************************************************************/
    public abstract class Awaitable<T> : AwaitableBase
    {
        public Awaitable<T> GetAwaiter()
        {
            return this;
        }

        public virtual T GetResult()
        {
            return default(T);
        }
    }

    /*******************************************************************************************/
    public abstract class UnsafeAwaitable : Awaitable, ICriticalNotifyCompletion
    {
        /// <summary>
        /// This method exists only to appease the compiler; derived classes need not interact with it.
        /// All derived classes, both safe and unsafe, should only implement OnCompleted().
        /// </summary>
        void ICriticalNotifyCompletion.UnsafeOnCompleted(Action continuation)
        {
            OnCompleted(continuation);
            return;
        }
    }

    /*******************************************************************************************/
    public abstract class UnsafeAwaitable<T> : Awaitable<T>, ICriticalNotifyCompletion
    {
        /// <summary>
        /// This method exists only to appease the compiler; derived classes need not interact with it.
        /// All derived classes, both safe and unsafe, should only implement OnCompleted().
        /// </summary>
        void ICriticalNotifyCompletion.UnsafeOnCompleted(Action continuation)
        {
            OnCompleted(continuation);
            return;
        }
    }
}
